package com.example.stack;

import java.util.Deque;
import java.util.LinkedList;

/**
 * @author wxz
 * <p>
 * 456. 132 模式
 * 给你一个整数数组 nums ，数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成，并同时满足：i < j < k 和 nums[i] < nums[k] < nums[j] 。
 * <p>
 * 如果 nums 中存在 132 模式的子序列 ，返回 true ；否则，返回 false 。
 * <p>
 * <p>
 * <p>
 * 进阶：很容易想到时间复杂度为 O(n^2) 的解决方案，你可以设计一个时间复杂度为 O(n logn) 或 O(n) 的解决方案吗？
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [1,2,3,4]
 * 输出：false
 * 解释：序列中不存在 132 模式的子序列。
 * <p>
 * <p>
 * <p>
 * 思路解析：单调栈（单调的栈，只存放比自己大或者小的数）
 * 1⃣️维护一个最大值。从右向左遍历数组，将数组的第一个值放入栈，
 * 2⃣️当栈不为空且栈顶元素小于当前遍历值的时候，出栈并更新当前值为栈顶元素(此处max更新为栈顶元素是因为栈顶元素代表了2，当前比栈顶大的这个数组遍历值是3，我们后续只要找到比2
 * 小的1即可精准的完成)
 * ⚠️如果执行了第二步，则已经找到了2和3，只需在找到比2，3小的1即可。此时如果数组元素一直是增的，那就入栈，直到找到小值即可返回。
 * 3⃣️将当前遍历值放入栈
 * 重复一二三步骤。如1，3，4，4，2
 * 4⃣️当当前遍历值小于max值时，返回成功，此时找到比max小的数，即132结构形成
 */
public class Pattern132 {
    public static void main(String[] args) {
        Pattern132 pattern132 = new Pattern132();
        int[] nums = {1, 3, 4, 4, 2};
        System.out.println(pattern132.find132pattern(nums));
    }

    public boolean find132pattern(int[] nums) {
        int n = nums.length;
        Deque<Integer> stack = new LinkedList<>();

        int max = Integer.MIN_VALUE;
        for (int i = n - 1; i >= 0; i--) {
            if (nums[i] < max) {
                return true;
            }
            while (!stack.isEmpty() && stack.peekLast() < nums[i]) {
                // 事实上，k 的变化也具有单调性，直接使用 k = pollLast() 也是可以的
                max = Math.max(max, stack.pollLast());
            }
            stack.addLast(nums[i]);
        }
        return false;
    }
}

